/**
 * History List GestionHistorique
 * va contenir des commande et states
 * Make singleton ????
 * caretaker
 */

//TODO IMPORANT Add trimlist to update action
//TODO Check new state creation macroenabled attributes
package Modele;

import Controleur.Controleur;
import java.util.ArrayList;

public class GestionHistorique implements UpdateHistoryReceiver{
	private ArrayList<State> savedStates = new ArrayList<State>();
        private Controleur ctrl;
        private int current_pos=0;

        public GestionHistorique(String buffer, int sel_debut,
                int sel_fin, boolean Selection, int position_cusor,
                String presse_papier, Character c) {
            savedStates.add(new State(buffer,sel_debut,sel_fin,
                    Selection,position_cusor,presse_papier,c, false));
        }

        public void setCtrl(Controleur ctrl) {
            this.ctrl = ctrl; }

	private void addMemento(State m) {
		savedStates.add(m);   
                current_pos++;
	}

        public State getCurrentState(){
            return savedStates.get(current_pos); }

        private void trimList() {
            while (isRedoable())
                savedStates.remove(savedStates.size()-1); }

    /********************************************************************
     * Update Action
     ********************************************************************/
    public void update_insert() {
        trimList();

        if (ctrl.isVTextSelected()){
            int pos = getCurrentState().getSel_debut();
            int fin = getCurrentState().getSel_fin();
            String buf = ctrl.getVBuffer().substring(0, pos) + ctrl.getVLastChar().toString() + ctrl.getVBuffer().substring(fin);
            addMemento(new State(buf,0, 0, false, ++pos, ctrl.getVPressePapier(), ctrl.getVLastChar(), true));
        } else {
            int pos = ctrl.getVCurseurPosition();
            String buf = ctrl.getVBuffer().substring(0, pos) + ctrl.getVLastChar().toString() + ctrl.getVBuffer().substring(pos);
            addMemento(new State(buf,0, 0, false, ++pos, ctrl.getVPressePapier(), ctrl.getVLastChar(), true));
        }
    }

    public void update_delete() {
        //On vérifie qu'on peut supprimer
        if (ctrl.getVBuffer().isEmpty()) return;

        trimList();
        
        if (ctrl.isVTextSelected()){
            int pos = getCurrentState().getSel_debut();
            int fin = getCurrentState().getSel_fin();
            String buf = ctrl.getVBuffer().substring(0, pos) + ctrl.getVBuffer().substring(fin);
            addMemento(new State(buf,0, 0, false, pos, ctrl.getVPressePapier(), ctrl.getVLastChar(), true));
        } else {
            int pos = ctrl.getVCurseurPosition();
            String buf = ctrl.getVBuffer().substring(0, pos-1) + ctrl.getVBuffer().substring(pos);
            addMemento(new State(buf,0, 0, false, --pos, ctrl.getVPressePapier(), ctrl.getVLastChar(), true));
        }
    }

    public void update_undo(){
        if (isUndoable()){
            --current_pos;
        } else
            getCurrentState().setUndoable(false);
    }

    public void update_redo() {
        if (isRedoable()) {
            ++current_pos;
        } else
            System.out.println("not redoable !!!!");
    }

    public void update_selection() {
        int debut = ctrl.getVCurseurPosition();
        int fin = ctrl.getVSelect_fin();
            if (debut<fin)
                addMemento(new State(ctrl.getVBuffer(),debut, fin, false, debut, ctrl.getVPressePapier(), ctrl.getVLastChar(), false));
            else
                addMemento(new State(ctrl.getVBuffer(),fin, debut, false, fin, ctrl.getVPressePapier(), ctrl.getVLastChar(), false));
    }

    public void update_copy(){
        if (!ctrl.isVTextSelected()) return;

        trimList();
        String t = ctrl.getVBuffer();
        String clipboard = t.substring(getCurrentState().getSel_debut(),getCurrentState().getSel_fin()) ;
        addMemento(new State(t,0, 0, false, ctrl.getVCurseurPosition(), clipboard, ctrl.getVLastChar(), true));
    }

    public void update_paste(){

        trimList();
        if (ctrl.isVTextSelected()){
            int pos = getCurrentState().getSel_debut();
            int fin = getCurrentState().getSel_fin();
            String buf = ctrl.getVBuffer().substring(0, pos) + ctrl.getVPressePapier() +ctrl.getVBuffer().substring(fin);
            addMemento(new State(buf,0, 0, false, pos+ctrl.getVPressePapier().length(), ctrl.getVPressePapier(), ctrl.getVLastChar(), true));
        } else {
            if (!ctrl.getVPressePapier().equalsIgnoreCase("")){
                int pos = ctrl.getVCurseurPosition();
                String t=ctrl.getVBuffer();
                String buffer = t.substring(0, pos) + ctrl.getVPressePapier() + t.substring(pos);
                addMemento(new State(buffer,0, 0, false, pos+ctrl.getVPressePapier().length(), ctrl.getVPressePapier(), ctrl.getVLastChar(), true));
            }
        }
    }

    public void update_cut(){
        trimList();

        if (ctrl.isVTextSelected()){
            int pos = getCurrentState().getSel_debut();
            int fin = getCurrentState().getSel_fin();
            String pp = ctrl.getVBuffer().substring(pos, fin);
            String buf = ctrl.getVBuffer().substring(0, pos) + ctrl.getVBuffer().substring(fin);
            addMemento(new State(buf,0, 0, false, pos, pp, ctrl.getVLastChar(), true));
        }
    }
    /********************************************************************
     * Get Model state - implement interface
     ********************************************************************/
    public String getMBuffer() {
        return getCurrentState().getBuffer();
    }

    public Character getMLastChar() {
        return getCurrentState().getLast_char();
    }

    public int getMCurrentPos() {
        return getCurrentState().getPosition_cusor();
    }

    public boolean isUndoable(){
        return (current_pos>0); }

    public boolean isRedoable(){
        return (current_pos<savedStates.size()-1);
    }

    public int getMSelect_fin() {
        return getCurrentState().getSel_fin();
    }

    public int getMSelect_debut(){
        return getCurrentState().getSel_debut();
    }

    public String getPressePapier(){
        return getCurrentState().getPresse_papier();
    }
}